// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "HAL/PlatformFilemanager.h"
#include "GenericPlatform/GenericPlatformFile.h"
#include "HAL/PlatformTime.h"
#include "HAL/FileManagerGeneric.h"

/**
 * Winston风格的日志系统类
 * 封装UE_LOG功能，提供更结构化的日志记录能力
 */
class EMPTYLAND_API FWinstonLogger
{
public:
    // 日志级别枚举
    enum class ELogLevel
    {
        Debug,
        Info,
        Warning,
        Error,
        Critical
    };

    /**
     * 获取日志系统单例实例
     * @return FWinstonLogger单例引用
     */
    static FWinstonLogger& Get();

    /**
     * 初始化日志系统
     * @param LogDirectory 日志文件保存目录
     * @param LogFileName 日志文件名前缀
     * @param bEnableFileLog 是否启用文件日志
     */
    void Initialize(const FString& LogDirectory = TEXT("Logs"), const FString& LogFileName = TEXT("EmptyLand"), bool bEnableFileLog = true);

    /**
     * 清理日志系统资源
     */
    void Shutdown();

    /**
     * 设置日志级别过滤器
     * @param Level 最低记录的日志级别
     */
    void SetLogLevel(ELogLevel Level);

    /**
     * 记录Debug级别日志
     * @param Category 日志分类
     * @param Format 日志格式化字符串
     * @param Args 格式化参数
     */
    template<typename... Args>
    void Debug(const FString& Category, const FString& Format, Args... Args);

    /**
     * 记录Info级别日志
     * @param Category 日志分类
     * @param Format 日志格式化字符串
     * @param Args 格式化参数
     */
    template<typename... Args>
    void Info(const FString& Category, const FString& Format, Args... Args);

    /**
     * 记录Warning级别日志
     * @param Category 日志分类
     * @param Format 日志格式化字符串
     * @param Args 格式化参数
     */
    template<typename... Args>
    void Warning(const FString& Category, const FString& Format, Args... Args);

    /**
     * 记录Error级别日志
     * @param Category 日志分类
     * @param Format 日志格式化字符串
     * @param Args 格式化参数
     */
    template<typename... Args>
    void Error(const FString& Category, const FString& Format, Args... Args);

    /**
     * 记录Critical级别日志
     * @param Category 日志分类
     * @param Format 日志格式化字符串
     * @param Args 格式化参数
     */
    template<typename... Args>
    void Critical(const FString& Category, const FString& Format, Args... Args);

private:
    // 私有构造函数，确保单例模式
    FWinstonLogger();
    // 析构函数
    ~FWinstonLogger();

    /**
     * 记录日志的内部方法
     * @param Level 日志级别
     * @param Category 日志分类
     * @param Message 日志消息
     */
    void LogInternal(ELogLevel Level, const FString& Category, const FString& Message);

    /**
     * 将日志级别转换为字符串
     * @param Level 日志级别
     * @return 日志级别的字符串表示
     */
    FString LevelToString(ELogLevel Level);

    /**
     * 获取当前时间的格式化字符串
     * @return 格式化的时间字符串
     */
    FString GetCurrentTimestamp();

    /**
     * 将日志写入文件
     * @param LogEntry 完整的日志条目
     */
    void WriteToLogFile(const FString& LogEntry);

private:
    ELogLevel CurrentLogLevel; // 当前日志级别过滤器
    bool bIsInitialized; // 是否初始化
    bool bEnableFileLogging; // 是否启用文件日志
    FString LogDir; // 日志目录
    FString LogFilePrefix; // 日志文件名前缀
    FString CurrentLogFilePath; // 当前日志文件路径
    IFileHandle* LogFileHandle; // 日志文件句柄
    FCriticalSection LogMutex; // 互斥锁，确保线程安全
};

// 模板方法实现
template<typename... Args>
void FWinstonLogger::Debug(const FString& Category, const FString& Format, Args... Args)
{
    if (CurrentLogLevel <= ELogLevel::Debug)
    {
        FString Message = FString::Printf(*Format, Args...);
        LogInternal(ELogLevel::Debug, Category, Message);
    }
}

template<typename... Args>
void FWinstonLogger::Info(const FString& Category, const FString& Format, Args... Args)
{
    if (CurrentLogLevel <= ELogLevel::Info)
    {
        FString Message = FString::Printf(*Format, Args...);
        LogInternal(ELogLevel::Info, Category, Message);
    }
}

template<typename... Args>
void FWinstonLogger::Warning(const FString& Category, const FString& Format, Args... Args)
{
    if (CurrentLogLevel <= ELogLevel::Warning)
    {
        FString Message = FString::Printf(*Format, Args...);
        LogInternal(ELogLevel::Warning, Category, Message);
    }
}

template<typename... Args>
void FWinstonLogger::Error(const FString& Category, const FString& Format, Args... Args)
{
    if (CurrentLogLevel <= ELogLevel::Error)
    {
        FString Message = FString::Printf(*Format, Args...);
        LogInternal(ELogLevel::Error, Category, Message);
    }
}

template<typename... Args>
void FWinstonLogger::Critical(const FString& Category, const FString& Format, Args... Args)
{
    if (CurrentLogLevel <= ELogLevel::Critical)
    {
        FString Message = FString::Printf(*Format, Args...);
        LogInternal(ELogLevel::Critical, Category, Message);
    }
}

// 方便使用的宏定义
#define WINSTON_DEBUG(Category, Format, ...) FWinstonLogger::Get().Debug(Category, Format, ##__VA_ARGS__)
#define WINSTON_LOG(Category, Message) FWinstonLogger::Get().Debug(Category, TEXT("%s"), *Message)
#define WINSTON_LOGF(Category, Format, ...) FWinstonLogger::Get().Debug(Category, Format, ##__VA_ARGS__)
#define WINSTON_INFO(Category, Message) FWinstonLogger::Get().Info(Category, TEXT("%s"), *Message)
#define WINSTON_INFOF(Category, Format, ...) FWinstonLogger::Get().Info(Category, Format, ##__VA_ARGS__)
#define WINSTON_WARN(Category, Message) FWinstonLogger::Get().Warning(Category, TEXT("%s"), *Message)
#define WINSTON_WARNF(Category, Format, ...) FWinstonLogger::Get().Warning(Category, Format, ##__VA_ARGS__)
#define WINSTON_ERROR(Category, Message) FWinstonLogger::Get().Error(Category, TEXT("%s"), *Message)
#define WINSTON_ERRORF(Category, Format, ...) FWinstonLogger::Get().Error(Category, Format, ##__VA_ARGS__)
#define WINSTON_CRITICAL(Category, Message) FWinstonLogger::Get().Critical(Category, TEXT("%s"), *Message)
#define WINSTON_CRITICALF(Category, Format, ...) FWinstonLogger::Get().Critical(Category, Format, ##__VA_ARGS__)